package com.yc.cloud.openai.portal.service.impl;

import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.Map;

import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.yc.cloud.common.basic.exception.Asserts;
import com.yc.cloud.common.basic.utils.PathUtils;
import com.yc.cloud.common.oss.service.OssFileService;
import com.yc.cloud.openai.entity.ModelRecord;
import com.yc.cloud.openai.portal.common.PortalErrorTips;
import com.yc.cloud.openai.portal.dao.ModelClient;
import com.yc.cloud.openai.portal.dto.PromptDto;
import com.yc.cloud.openai.portal.dto.request.ImageToModelRequest;
import com.yc.cloud.openai.portal.dto.request.TextToModelRequest;
import com.yc.cloud.openai.portal.enums.ModelProvider;
import com.yc.cloud.openai.portal.enums.PromptType;
import com.yc.cloud.openai.portal.factory.ModelClientFactory;
import com.yc.cloud.openai.portal.service.ModelRecordService;
import com.yc.cloud.openai.portal.service.ModelService;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import lombok.SneakyThrows;
import lombok.val;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class ModelServiceImpl implements ModelService {

    private final Map<ModelProvider, ModelClient> modelClientMap;
    private final PathUtils pathUtils;
    private final OssFileService ossFileService;
    private final ModelRecordService modelRecordService;

    public ModelServiceImpl(ModelClientFactory clientFactory, PathUtils pathUtils,
            OssFileService ossFileService, ModelRecordService modelRecordService) {
        this.modelClientMap = clientFactory.getClientMap();
        this.pathUtils = pathUtils;
        this.ossFileService = ossFileService;
        this.modelRecordService = modelRecordService;
    }

    @Override
    public PromptDto textToModel(TextToModelRequest param) {
        ModelClient client = modelClientMap.get(param.getProvider());
        if (client == null) {
            Asserts.fail(PortalErrorTips.PROVIDER_NOT_FOUND);
            return null;
        }
        val promptDto = client.convertTextToModel(param);
        if (StrUtil.isNotEmpty(promptDto.getPromptId())) {
            generateModelRecord(param.getProvider().getKey(), param.getPrompt(), promptDto, null);
        }
        return promptDto;
    }

    @Override
    @SneakyThrows
    public PromptDto imageToModel(ImageToModelRequest param, MultipartFile multipartFile) {
        ModelClient client = modelClientMap.get(param.getProvider());
        if (client == null) {
            Asserts.fail(PortalErrorTips.PROVIDER_NOT_FOUND);
            return null;
        }
        // multipartfile 转file,保存到磁盘上,按照clientId创建文件夹
        val newFileName = System.currentTimeMillis() + "." + FileUtil.getSuffix(multipartFile.getOriginalFilename());
        val path = Paths.get(pathUtils.getBasePath(), param.getClientId(), newFileName);
        val file = FileUtil.writeBytes(multipartFile.getBytes(), path.toFile());
        val promptDto = client.convertImageToModel(param, file);
        if (StrUtil.isNotEmpty(promptDto.getPromptId())) {
            // 构建ossfile 和 modelrecord
            val ossFile = ossFileService.saveOssFile(path.toString());
            var sampleFileId = "";
            if (ossFile != null) {
                // 上传的参考图文件ID
                sampleFileId = ossFile.getFileId();
            }
            generateModelRecord(param.getProvider().getKey(), null, promptDto, sampleFileId);
        }
        return promptDto;
    }

    // 生成图片转3D模型的记录
    private boolean generateModelRecord(String provider, String prompt, PromptDto promptDto,
            String sampleFileId) {
        val modelRecord = new ModelRecord();
        // 客户端ID
        modelRecord.setClientId(promptDto.getClientId());
        // 参考图文件ID
        modelRecord.setSampleFileId(sampleFileId);
        // 提示词内容
        // imageRecord.setPrompt(imageToModelRequest.getPrompt());
        // 设置任务ID
        modelRecord.setUuid(promptDto.getPromptId());
        // 设置生成图片的类型为文生图枚举值
        if (StrUtil.isNotEmpty(prompt)) {
            modelRecord.setType(PromptType.TEXT2MODEL.getKey());
        } else {
            modelRecord.setType(PromptType.IMAGE2MODEL.getKey());
        }
        modelRecord.setCreateTime(LocalDateTime.now());
        modelRecord.setProvider(provider);
        modelRecord.setPrompt(prompt);
        return modelRecordService.save(modelRecord);
    }

}
